import math
from yangke.base import PolyCurve, plot_3d
from yangke.common.config import logger
import tqdm
import tkinter as tk


A1 = [2650, 14.5, 0.0345, 4.2, 0.030, 0.031]  # 机组系数
A2 = [1250, 36.0, 0.0435, 0.6, 0.027, 0.011]
A3 = [0, 50, 0, 0, 0, 0]
A4 = [0, 0, 0, 23.4, 0, 0]


def cost(a, p, h):
    # if in_range(p, h):
    return a[0] + a[1] * p + a[2] * p * p + a[3] * h + a[4] * h * h + a[5] * p * h
    # else:
    #     return 100000000


# =================================================================12号机组热电可行域函数
fun11 = PolyCurve([104.8, 0], [81, 98.8]).func
fun12 = PolyCurve([104.8, 180], [81, 215]).func
fun13 = PolyCurve([180, 0], [215, 247]).func

# =================================================================34号机组热电可行域函数
fun21 = PolyCurve([15.9, 0], [44, 44]).func
fun22 = PolyCurve([75, 15.9], [40, 44]).func
fun23 = PolyCurve([135.6, 75], [110.2, 40]).func
fun24 = PolyCurve([32.4, 135.6], [125.8, 110.2]).func
fun25 = PolyCurve([0, 32.4], [125.8, 125.8]).func


# =================================================================设置小数位数函数
def set_value(a, b=2):
    c = f"{a:10.{b}f}"
    return c


# =================================================================12号机组电功率下边界
def get_minp_by_h1(h):
    if h <= 104.8:
        pmin = fun11(h)
    elif h <= 180:
        pmin = fun12(h)
    else:
        pmin = 81
    return pmin


# =================================================================12号机组电功率上边界
def get_maxp_by_h1(h):
    if 32.4 < h <= 135.6:
        pmax = fun13(h)
    else:
        pmax = 126
    return pmax


# =================================================================34号机组电功率下边界
def get_minp_by_h2(h):
    if h <= 15.9:
        pmin = fun21(h)
    elif h <= 75:
        pmin = fun22(h)
    elif h <= 135.6:
        pmin = fun23(h)
    else:
        pmin = 40
    return pmin


# =================================================================34号机组电功率上边界
def get_maxp_by_h2(h):
    if 32.4 < h <= 135.6:
        pmax = fun24(h)
    elif h <= 32.4:
        pmax = fun25(h)
    else:
        pmax = 126
    return pmax


def in_range1(p=0, h=0):
    if get_minp_by_h1(h) < p < get_maxp_by_h1(h) and 0 < p < 660:
        return True


def in_range2(p=0, h=0):
    if get_minp_by_h2(h) < p < get_maxp_by_h2(h) and 0 < p < 660:
        return True


def calculate(p_total=0, h_total=0, p1=660, p2=660, p3=1000, p4=1000, h1=0, h2=0, h3=0, h4=0, dp1=10, dp2=10, a1=[],
              a2=[], a3=[], a4=[]):
    interval = 2
    p10 = p1
    p20 = p2
    p30 = p3
    p40 = p4
    cost1 = cost(a1, p1, h1)
    cost2 = cost(a2, p2, h2)
    cost3 = cost(a3, p3, h3)
    cost4 = cost(a4, p4, h4)
    cost0 = cost1 + cost2 + cost3 + cost4
    min_cost = 10000000
    min_p1, min_p2, min_p3, min_p4 = 0, 0, 0, 0
    min_h1, min_h2, min_h3, min_h4 = 0, 0, 0, 0

    # ---------------------------------------------------------------------------1号机组循环
    if p1 == 0:  # 设置1号机组热负荷循环上下限,如果停机则不循环
        h1max = 1
    else:
        h1max = h_total + 1
    h1max = min(h1max, 180)  # 手动定义1号机组最大热负荷
    i = 0
    for h1 in tqdm.tqdm(range(0, h1max, interval)):  # tqdm---进度条
        if p1 == 0:  # 设置1号机组电功率循环上下限,如果停机则不循环
            p1min = 0
            p1max = 1
        else:
            # if int(get_minp_by_h1(h1)) > p10 - dp1:  # 用dp1和h1限制1号机组电功率循环上下限
            #     p1min = int(get_minp_by_h1(h1))
            # else:
            #     p1min = p10 - dp1
            # if math.ceil(min(get_maxp_by_h1(h1), p_total)) + 1 < p10 + dp1:
            #     p1max = math.ceil(min(get_maxp_by_h1(h1), p_total)) + 1
            # else:
            #     p1max = p10 + dp1
            p1min = max(p10 - dp1, int(get_minp_by_h1(h1)))
            p1max = min(math.ceil(min(get_maxp_by_h1(h1), p_total)) + 1, p10 + dp1)
        for p1 in range(p1min, p1max, interval):
            # ---------------------------------------------------------------------------2号机组循环
            if p2 == 0:
                h2max = 1
            else:
                h2max = h_total - h1
            h2max = int(min(h2max, 136))  # 手动输入2号机组最大热负荷
            for h2 in range(0, h2max, interval):
                if p2 == 0:  # 设置2号机组电功率循环上下限,如果停机则不循环
                    p2min = 0
                    p2max = 1
                else:
                    # if int(get_minp_by_h2(h2)) > p20 - dp1:  # 用dp1和h2限制2号机组电功率循环上下限
                    #     p2min = int(get_minp_by_h2(h2))
                    # else:
                    #     p2min = p20 - dp1
                    # if int(min(get_maxp_by_h2(h2), p_total - p1)) < p20 + dp1:
                    #     p2max = int(min(get_maxp_by_h2(h2), p_total - p1)) + 1
                    # else:
                    #     p2max = p20 + dp1
                    p2min = max(int(get_minp_by_h2(h2)), p20 - dp1)
                    p2max = min(math.ceil(min(get_maxp_by_h2(h2), p_total - p1)) + 1, p20 + dp1)
                for p2 in range(p2min, p2max, interval):
                    # ---------------------------------------------------------------------------3号机组循环
                    p3 = p_total - p1 - p2
                    h3 = 0
                    h4 = h_total - h1 - h2
                    p4 = 0
                    # if p1 == 0:
                    #     cost1 = 0
                    # else:
                    #     cost1 = cost(A1, p1, h1)
                    # if p2 == 0:
                    #     cost2 = 0
                    # else:
                    #     cost2 = cost(A2, p2, h2)
                    # ---------------------------------------------------------------------------成本计算
                    cost1 = cost(A1, p1, h1)
                    cost2 = cost(A2, p2, h2)
                    cost3 = cost(A3, p3, h3)
                    cost4 = cost(A4, p4, h4)
                    cost_total = cost1 + cost2 + cost3 + cost4
                    i = i + 1
                    # ---------------------------------------------------------------------------最小成本计算
                    if cost_total < min_cost:
                        min_cost = cost_total
                        min_p1 = p1
                        min_h1 = h1
                        min_p2 = p2
                        min_h2 = h2
                        min_p3 = p3
                        min_h3 = h3
                        min_p4 = p4
                        min_h4 = h4
                        min_c1 = cost1
                        min_c2 = cost2
                        min_c3 = cost3
                        min_c4 = cost4
    logger.debug(i)
    return min_p1, min_p2, min_p3, min_p4, min_h1, min_h2, min_h3, min_h4, min_c1, min_c2, min_c3, min_c4, cost0
    # logger.debug(f"{min_p1=}, {min_h1=}")
    # logger.debug(f"{min_p2=}, {min_h2=}")
    # logger.debug(f"{min_p3=}, {min_h3=}")
    # logger.debug(f"{min_p4=}, {min_h4=}")


def isNum(num):
    try:

        n = type(eval(num))

        if n == type(1):  # 输入为整型

            return True

        elif n == type(1.0):  # 输入为浮点型

            return True

        elif n == type(1 + 1j):  # 输入为复数

            return True
    except:

        return False

# p_totalcheck = p1 + p2 + p3 + p4
# h_totalcheck = h1 + h2 + h3 + h4
# # cost1 = cost(A1, min_p1, min_h1)
# # cost2 = cost(A2, min_p2, min_h2)
# # cost3 = cost(A3, min_p3, min_h3)
# # cost4 = cost(A4, min_p4, min_h4)

# logger.debug(f"{min_cost=}")
# logger.debug(f"{p_totalcheck=}, {h_totalcheck=}")
# print(xyz)
# plot_3d(xyz[0], xyz[1], xyz[2])
# pd.DataFrame(xyz).to_excel("sh.xlsx")
# pd.DataFrame(xyz2).to_excel("sh2.xlsx")
# pd.DataFrame(xyz3).to_excel("sh3.xlsx")
# pd.DataFrame(xyz4).to_excel("sh4.xlsx")
